Skip to content

Conversation

@thecrypticace
Copy link
Contributor

@thecrypticace thecrypticace commented Nov 19, 2025

Fixes #18114
Closes #18115

This PR changes JS config handling such that we always preserve casing for theme keys (when possible).

Now there are two exceptions to this rule:

  1. Top-level keys in the theme do get converted to kebab-case. As CSS variables are not generated from these this shouldn't be a big issue.

All of our internal plugins look for kebab-case keys. So, for example, take the path backgroundColor.red.500. This must translate to --background-color-red-500. But if you had something like backgroundColor.lightBlue it would be perfectly fine for that to translate to --background-color-lightBlue internally (and thus the utility be written as bg-lightBlue.

  1. Tuple object keys are converted to kebab-case as well.

These keys are converted to "nested" key syntax internally and typtically represent CSS property names.

For example:

export default {
  theme: {
    fontSize: {
      xs: ["1.5rem", { lineHeight: "1.3" }]
    },
    
    fontFamily: {
      sans: ["Potato Mono", { fontVariationSettings: '"XHGT" 0.7' }]
    }
  }
}

The lineHeight key here must be converted to line-height because it represents a CSS property name. The theme key that represents this value is --text-xs--line-height. The same situation applies for the fontVariationSettings where the theme key is --font-sans--font-variation-settings.

@thecrypticace thecrypticace marked this pull request as ready for review November 20, 2025 19:41
@thecrypticace thecrypticace requested a review from a team as a code owner November 20, 2025 19:41
@coderabbitai
Copy link

coderabbitai bot commented Nov 20, 2025

Walkthrough

This PR preserves camelCase theme keys from JS configs and plugins. Tests and snapshots were updated to use camelCase tokens and class names. The keyPathToCssProperty transformation was changed to conditionally kebab-case path segments (first namespace part, tuple-nested keys indicated by leading '-', and the special lineHeight case) while leaving other segments as-is. A new test verifies camelCase theme keys generate expected utilities. The changelog documents the behavior change.

Pre-merge checks

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: preventing unconditional kebab-case conversion of config keys.
Description check ✅ Passed The description clearly explains the changes, provides context for the two exceptions, and references the fixed issues.
Linked Issues check ✅ Passed The PR addresses both #18114 and #18115 by selectively preserving camelCase keys except for top-level theme keys and tuple object keys.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the camelCase-to-kebab-case conversion issues; test updates and CHANGELOG entry are appropriate.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Member

@RobinMalfait RobinMalfait left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense that if your own names for values were described in camelCase that it should stay as camelCase instead of being converted to kebab-case.

This could be a breaking change technically, but then you already had a breaking change in the first place (because your camelCase name was converted to a kebab-case name).

If it causes too much trouble for people, we could enable both (and probably show a warning that you have a casing mismatch and that you should either convert the source or the usages).

@thecrypticace
Copy link
Contributor Author

Yeah, I think if this causes issues then we can try to do something similar to #18115 in addition to this PR to address that.

@thecrypticace thecrypticace enabled auto-merge (squash) November 20, 2025 22:35
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
CHANGELOG.md (1)

17-17: Clarify exceptions and cross-link issues in the changelog entry.

Spell out the kebab-case exceptions (top-level theme keys and tuple object keys) and link the fixed issues for traceability.

- - Preserve case of theme keys from JS configs and plugins ([#19337](https://github.com/tailwindlabs/tailwindcss/pull/19337))
+ - Preserve case of theme keys from JS configs and plugins, except:
+   - top‑level `theme` keys (still kebab‑cased), and
+   - tuple object keys used as CSS property names (still kebab‑cased, e.g., `lineHeight` → `line-height`)
+   ([#19337](https://github.com/tailwindlabs/tailwindcss/pull/19337), fixes [#18114](https://github.com/tailwindlabs/tailwindcss/issues/18114), closes [#18115](https://github.com/tailwindlabs/tailwindcss/issues/18115))
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cbd0cc8 and cc3bc85.

📒 Files selected for processing (2)
  • CHANGELOG.md (1 hunks)
  • integrations/upgrade/js-config.test.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • integrations/upgrade/js-config.test.ts

@thecrypticace thecrypticace merged commit 642b9b8 into main Nov 20, 2025
7 checks passed
@thecrypticace thecrypticace deleted the fix/issue-18114 branch November 20, 2025 22:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Utility class name transforms lowercase+uppercase keys (camelCase/PascalCase) to kebab-case unexpectedly when using JavaScript config file

3 participants